package com.platform.tony.config;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.platform.tony.common.Constant;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


@Slf4j
@Setter
@Getter
public class EmailAuthFilter extends AbstractAuthenticationProcessingFilter {


    private Boolean postOnly = true;

    private StringRedisTemplate template;

    public EmailAuthFilter() {
        super(new AntPathRequestMatcher(Constant.EMAIL_URI, "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String contentType = request.getContentType();
        log.info("content type is {}", contentType);
        Map<String, String> params = new HashMap<>(2);
        // 请求头信息
        if (StrUtil.equals(contentType, MediaType.APPLICATION_JSON_VALUE)) {
            log.info("content type is {}", request.getContentType());
            params = new ObjectMapper().readValue(request.getInputStream(), new TypeReference<Map<String, String>>() {});
        }
        if (StrUtil.equals(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
            String parameter1 = request.getParameter(Constant.EMAIL);
            String parameter2 = request.getParameter(Constant.CODE);
            params.put(Constant.EMAIL, parameter1);
            params.put(Constant.CODE, parameter2);
        }

        String email = params.get(Constant.EMAIL);
        String code = params.get(Constant.CODE);
        // 从缓存中获取验证码
        String verify = template.opsForValue().get(Constant.EMAIL_CODE_PREFIX + email);
        if (StrUtil.isBlank(verify)) {
            throw new AuthenticationServiceException("请重新申请验证码!");
        }
        // 验证码错误
        if (!StrUtil.equals(code, verify)) {
            throw new AuthenticationServiceException("验证码错误!");
        }
        log.info("params email {} and code {}", email, code);

        EmailAuthToken token = new EmailAuthToken(email);
        token.setDetails(super.authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(token);
    }

}
